package com.anrong.sdk;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import net.lingala.zip4j.exception.ZipException;

import org.apache.tools.ant.taskdefs.Zip;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.anrong.sdk.callback.InitCallBack;
import com.anrong.sdk.callback.ZipCallBack;
import com.anrong.sdk.util.log.LogUtil;
import com.arong.swing.config.EquiptMonitorCont;
import com.arong.swing.db.dao.AsAllGenerateSDAO;
import com.arong.swing.db.dao.CrBidCarSDAO;
import com.arong.swing.db.dao.CrBidPersonSDAO;
import com.arong.swing.db.dao.CrCarRecordSDAO;
import com.arong.swing.db.dao.CrCheckeventSDAO;
import com.arong.swing.db.dao.CrDoubtfulCarSDAO;
import com.arong.swing.db.dao.CrDoubtfulPersonSDAO;
import com.arong.swing.db.dao.CrHcManagementSDAO;
import com.arong.swing.db.dao.CrPersionRecordSDAO;
import com.arong.swing.db.dao.DeptSDAO;
import com.arong.swing.db.dao.EquipmentSDAO;
import com.arong.swing.db.dao.EquiptMonitorSDAO;
import com.arong.swing.db.dao.StaffSDAO;
import com.arong.swing.db.dao.StaffUserSDAO;
import com.arong.swing.db.dao.TaskScopeSDAO;
import com.arong.swing.db.entity.AsAllGenerate;
import com.arong.swing.db.entity.CrBidCar;
import com.arong.swing.db.entity.CrBidPerson;
import com.arong.swing.db.entity.CrCarRecord;
import com.arong.swing.db.entity.CrCheckevent;
import com.arong.swing.db.entity.CrDoubtfulCar;
import com.arong.swing.db.entity.CrDoubtfulPerson;
import com.arong.swing.db.entity.CrHcManagement;
import com.arong.swing.db.entity.CrPersionRecord;
import com.arong.swing.db.entity.Dept;
import com.arong.swing.db.entity.Equipment;
import com.arong.swing.db.entity.EquiptMonitor;
import com.arong.swing.db.entity.JsonDataResult;
import com.arong.swing.db.entity.KeyCar;
import com.arong.swing.db.entity.KeyPerson;
import com.arong.swing.db.entity.Staff;
import com.arong.swing.db.entity.StaffUser;
import com.arong.swing.db.entity.StaffUserVO;
import com.arong.swing.db.entity.TaskScope;
import com.arong.swing.exception.AppException;
import com.arong.swing.exception.SysException;
import com.arong.swing.util.MD5Impl;

/**
 * 
 * @author hushunyi
 * 
 */
public final class SDKService {
	private static String UTF_8 = "UTF-8";
	private static String TAG = "SDKService";

	private static String ANRONG_DATAS_PATHDIR = null;
	private static String ANRONGTEC_DB = null;
	private static String CHECKRECORDUPLOAD_DB = null;
	private static String DEVRECORDUPLOAD_DB = null;
	private static AsAllGenerate loginCurAsAllGenerate = null;
	private static Equipment loginEqt = null;
	private static Dept curDept = null;
	private static StaffUser checkUser = null;// 核查人,可能是辅警StaffUser
	public static Staff formalPolice = null;// 归属警员，即正式警员
	private static String company_ID = null;
	// log输出文件
	private static String ANRONG_LOG_PATHDIR;

	private SDKService() {
	}

	/**
	 * 提供统一的32为UUID
	 * 
	 * @return
	 */
	public static String uuid32() {
		UUID uuid = UUID.randomUUID();
		return uuid.toString().replaceAll("-", "");
	}

	public synchronized static void addMonitorRecord(EquiptMonitor monitorEntity)
			throws Exception {
		// 添加设备活动日志
		EquiptMonitorSDAO equiptMonitorSDAO = new EquiptMonitorSDAO(
				DEVRECORDUPLOAD_DB);
		equiptMonitorSDAO.insert(monitorEntity);
	}

	/**
	 * 
	 * @Title: init
	 * @Description: 新版初始化信息 ,线程同步
	 * @param @param appRootPath
	 * @param @param IMEI
	 * @param @param companyID
	 * @param @param callback
	 * @return void 返回类型
	 * @throws
	 */
	public static void init(Application application, String appRootPath,
			String IMEI, String companyID, InitCallBack callback) {
		if (callback == null) {
			throw new NullPointerException("回调接口 CallBack 不可为空");
		}
		// 初始化路径
		ANRONG_DATAS_PATHDIR = appRootPath + "/anrong/infocheck/datas/";
		ANRONGTEC_DB = ANRONG_DATAS_PATHDIR + "anrongtec.db";
		CHECKRECORDUPLOAD_DB = ANRONG_DATAS_PATHDIR + "checkRecordUpload.db";
		DEVRECORDUPLOAD_DB = ANRONG_DATAS_PATHDIR + "devRecordUpload.db";
		ANRONG_LOG_PATHDIR = appRootPath + "/anrong/infocheck/log/";
		// 初始化Log
		LogUtil.init(Log.DEBUG, ANRONG_LOG_PATHDIR, false);
		LogUtil.processGlobalException(application, true);
		// 初始化文件
		File fileDir = new File(ANRONG_DATAS_PATHDIR);
		if (!fileDir.exists()) {
			fileDir.mkdirs();
		}
		try {
			// 获取登录的设备信息
			EquipmentSDAO equipmentSDAO = new EquipmentSDAO(ANRONGTEC_DB);
			Equipment isRegister = equipmentSDAO.queryBeanByEuqID(IMEI);
			if (isRegister == null) {
				isRegister = new Equipment();
				isRegister.setEquiptId(IMEI);
				isRegister.setImsi(IMEI);
				equipmentSDAO.insert(isRegister);
			}
			loginEqt = isRegister;
			if (equipmentSDAO.count() > 1) {
				callback.onError(InitCallBack.CODE_DEVICE_REGISTER_EXCEPTION,
						InitCallBack.MSG_DEVICE_REGISTER);
				return;
			}
			// 加载本地检查站信息
			if (loginEqt.getDeptId() != null) {
				DeptSDAO deptDao = new DeptSDAO(ANRONGTEC_DB);
				Dept deptQuery = new Dept();
				deptQuery.setDeptId(loginEqt.getDeptId());
				deptQuery = deptDao.queryBean(deptQuery);
				if (deptQuery != null) {
					curDept = deptQuery;
				} else {
					callback.onError(
							InitCallBack.CODE_ORGANIZATION_REGISTER_EXCEPTION,
							InitCallBack.MSG_ORGANIZATION_REGISTER);
					return;
				}
				// 移动设备未注册
			} else {
				callback.onError(
						InitCallBack.CODE_MOBILE_DEVICE_NOT_REGISTERED,
						InitCallBack.MSG_MOBILE_DEVICE_NOT_REGISTERED);
			}
			// 检测companyID
			if (TextUtils.isEmpty(companyID)) {
				callback.onError(InitCallBack.CODE_COMPANYID_EMPTY_EXCEPTION,
						InitCallBack.MSG_COMPANYID_EMPTY);
				return;
			}
			company_ID = companyID; //
			// 还有个需求需要考虑，就是 怎么保证 移动设备和台式机的时间 一致??

			// 核查记录如果一定时间不上传 就要限制用户使用，强制要求回传核查记录数据??
			CrCheckeventSDAO crCheckeventSDAO = new CrCheckeventSDAO(
					CHECKRECORDUPLOAD_DB);
			CrCheckevent latestEvent = crCheckeventSDAO.queryMaxTimeBean();
			long countNum = crCheckeventSDAO.count();
			if (countNum > 3000
					|| (latestEvent != null
							&& latestEvent.getStartTime() != null && System
							.currentTimeMillis()
							- latestEvent.getStartTime().getTime() > 3 * 24 * 3600 * 1000)) {
				callback.onError(InitCallBack.CODE_UPLOAD_NOTINTIME_EXCEPTION,
						InitCallBack.MSG_UPLOAD_NOTINTIME);
				return;
			}
			//
			// 先获取本地的布控包版本
			AsAllGenerateSDAO asAllGenerateSDAO = new AsAllGenerateSDAO(
					ANRONGTEC_DB);
			loginCurAsAllGenerate = asAllGenerateSDAO.getLatest();
			if (loginCurAsAllGenerate == null) {
				callback.onError(
						InitCallBack.CODE_CTRL_PACKET_NOTEXIST_EXCEPTION,
						InitCallBack.MSG_CTRL_PACKET_NOTEXIST);
				return;
			}
			// 如果有最新的布控压缩包进行解压(应该是先解压临时文件，然后把原文件夹删除，然后再将临时文件改为正式文件夹),解压完后进行删除压缩包
			String zipFilePath = ANRONG_DATAS_PATHDIR + "wholePackage.zip";
			final File zipFile = new File(zipFilePath);
			if (zipFile.exists()) {
				callback.onNeedExplode(InitCallBack.CODE_NEED_EXPLODE);
				return;
			} else {
				LogUtil.trace(Log.WARN, TAG, zipFilePath + ":不存在");
			}
			callback.onSuccess(InitCallBack.CODE_INIT_SUCCESS);
		} catch (SysException e) {
			callback.onError(InitCallBack.CODE_ERROR_EXCEPTION, "SysException ");
			e.printStackTrace();
		} catch (AppException e) {
			e.printStackTrace();
			callback.onError(InitCallBack.CODE_ERROR_EXCEPTION, "AppException ");
		}
	}

	/**
	 * 解压缩
	 * 
	 * @Title: explode
	 * @Description: (这里用一句话描述这个方法的作用)
	 * @param
	 * @return void 返回类型
	 * @throws
	 */
	public static void explode(Activity activity, final ZipCallBack zipCallBack) {
		// 如果有最新的布控压缩包进行解压(应该是先解压临时文件，然后把原文件夹删除，然后再将临时文件改为正式文件夹),解压完后进行删除压缩包
		String zipFilePath = ANRONG_DATAS_PATHDIR + "wholePackage.zip";
		final File zipFile = new File(zipFilePath);
		if (zipFile.exists()) {
			String filePath = ANRONG_DATAS_PATHDIR + "package";
			try {
				UnZipUtil.upZip(activity, zipFile, filePath, zipCallBack);
			} catch (final ZipException e) {
				zipCallBack.onError(
						ZipCallBack.CODE_EXPLODE_PACKET_FAILED_EXCEPTION,
						ZipCallBack.MSG_EXPLODE_PACKET_FAILED);
				e.printStackTrace();
			}
		} else {
			zipCallBack.onError(
					ZipCallBack.CODE_EXPLODE_PACKET_NOTEXIST_EXCEPTION,
					ZipCallBack.MSG_EXPLODE_PACKET_NOTEXIST);
		}

	}

	// /**
	// *
	// * @param appRootPath
	// * app所在盘符的根目录
	// * @param IMEI
	// * 设备的IMEI号,唯一
	// * @param companyID
	// * 公司英文简称,字典常量字符串,需向安荣科技申请
	// * @return JsonDataResult的code值为000表示成功,结果为泛型对象T;非000则失败,失败原因为msg
	// * @throws Exception
	// */
	// public static JsonDataResult<String> init(String appRootPath, String
	// IMEI,
	// String companyID, ZipCallBack zipCallback) throws Exception {
	// if (zipCallback == null) {
	// throw new NullPointerException("回调接口 zipCallBack 不可为空");
	// }
	// callback = zipCallback;
	// JsonDataResult<String> jr = new JsonDataResult<String>();
	//
	// ANRONG_DATAS_PATHDIR = appRootPath + "/anrong/infocheck/datas/";
	// ANRONGTEC_DB = ANRONG_DATAS_PATHDIR + "anrongtec.db";
	// CHECKRECORDUPLOAD_DB = ANRONG_DATAS_PATHDIR + "checkRecordUpload.db";
	// DEVRECORDUPLOAD_DB = ANRONG_DATAS_PATHDIR + "devRecordUpload.db";
	//
	// File fileDir = new File(ANRONG_DATAS_PATHDIR);
	// if (!fileDir.exists()) {
	// fileDir.mkdirs();
	// }
	//
	// // 获取登录的设备信息
	// EquipmentSDAO equipmentSDAO = new EquipmentSDAO(ANRONGTEC_DB);
	// Equipment isRegister = equipmentSDAO.queryBeanByEuqID(IMEI);
	// if (isRegister == null) {
	// isRegister = new Equipment();
	// isRegister.setEquiptId(IMEI);
	// isRegister.setImsi(IMEI);
	// equipmentSDAO.insert(isRegister);
	// }
	// loginEqt = isRegister;
	// if (equipmentSDAO.count() > 1) {
	// callback.onError(020, "设备注册信息IMEI非法！");
	// jr.setCode("020");
	// jr.setMsg("设备注册信息IMEI非法！");
	// return jr;
	// }
	//
	// // 加载本地检查站信息
	// if (loginEqt.getDeptId() != null) {
	// DeptSDAO deptDao = new DeptSDAO(ANRONGTEC_DB);
	// Dept deptQuery = new Dept();
	// deptQuery.setDeptId(loginEqt.getDeptId());
	// deptQuery = deptDao.queryBean(deptQuery);
	// if (deptQuery != null) {
	// curDept = deptQuery;
	// } else {
	// callback.onError(021, "不存在注册的组织机构，请同步更新注册设备信息！");
	// jr.setCode("021");
	// jr.setMsg("不存在注册的组织机构，请同步更新注册设备信息！");
	// return jr;
	// }
	// }
	//
	// if (companyID == null || companyID.trim().length() < 1) {
	// callback.onError(022, "companyID 为空！");
	// jr.setCode("022");
	// jr.setMsg("companyID 为空！");
	// return jr;
	// }
	// company_ID = companyID; //
	//
	// // 还有个需求需要考虑，就是 怎么保证 移动设备和台式机的时间 一致??
	//
	// // 核查记录如果一定时间不上传 就要限制用户使用，强制要求回传核查记录数据??
	// CrCheckeventSDAO crCheckeventSDAO = new CrCheckeventSDAO(
	// CHECKRECORDUPLOAD_DB);
	// CrCheckevent latestEvent = crCheckeventSDAO.queryMaxTimeBean();
	// long countNum = crCheckeventSDAO.count();
	// if (countNum > 3000
	// || (latestEvent != null && latestEvent.getStartTime() != null && System
	// .currentTimeMillis()
	// - latestEvent.getStartTime().getTime() > 3 * 24 * 3600 * 1000)) {
	// callback.onError(024, "请及时上传核查数据！");
	// jr.setCode("024");
	// jr.setMsg("请及时上传核查数据！");
	// return jr;
	// }
	// // 如果有最新的布控压缩包进行解压(应该是先解压临时文件，然后把原文件夹删除，然后再将临时文件改为正式文件夹),解压完后进行删除压缩包
	// String zipFilePath = ANRONG_DATAS_PATHDIR + "wholePackage.zip";
	// final File zipFile = new File(zipFilePath);
	// if (zipFile.exists()) {
	// if (callback.onPrepare()) {
	// String filePath = ANRONG_DATAS_PATHDIR + "package";
	// UnZipUtil.upZip(zipFile, filePath, callback);
	// } else {
	// callback.onError(ZipCallBack.ERROR_EXCEPTION, "解压缩初始化异常");
	// }
	// } else {
	// Log.w(TAG, zipFilePath + ":不存在");
	// }
	// // if (zipFile.exists()) {
	// // try {
	// // // File packageDir = new File(ANRONG_DATAS_PATHDIR + "package");
	// // ZipCompressorByAnt.deleteAllFiles(packageDir);
	// //
	// // File packageTmp = new File(ANRONG_DATAS_PATHDIR + "package");
	// // ZipCompressorByAnt.unzip(zipFile, packageTmp);
	// //
	// // ZipCompressorByAnt.deleteAllFiles(zipFile);// 解压完后进行删除压缩包
	// // } catch (Exception e) {
	// // callback.onError(025, "布控包解压失败，请重新同步最新布控包！");
	// // jr.setCode("025");
	// // jr.setMsg("布控包解压失败，请重新同步最新布控包！");
	// // return jr;
	// // }
	// // }
	//
	// // 先获取本地的布控包版本
	// AsAllGenerateSDAO asAllGenerateSDAO = new AsAllGenerateSDAO(
	// ANRONGTEC_DB);
	// loginCurAsAllGenerate = asAllGenerateSDAO.getLatest();
	// if (loginCurAsAllGenerate == null) {
	// callback.onError(023, "布控包不存在，请同步最新布控包！");
	// jr.setCode("023");
	// jr.setMsg("布控包不存在，请同步最新布控包！");
	// return jr;
	// }
	// callback.onSuccess();
	// return jr;
	// }

	/**
	 * 获取当前的布控版的版本
	 * 
	 * @return
	 * @throws Exception
	 */
	public static AsAllGenerate getCurAsAllGenerate() throws Exception {
		if (loginCurAsAllGenerate == null) {
			AsAllGenerateSDAO asAllGenerateSDAO = new AsAllGenerateSDAO(
					ANRONGTEC_DB);
			loginCurAsAllGenerate = asAllGenerateSDAO.getLatest();
			if (loginCurAsAllGenerate == null) {
				LogUtil.trace(Log.ERROR, TAG, "getCurAsAllGenerate 布控包信息为空");
			}
		}
		return loginCurAsAllGenerate;
	}

	/**
	 * 获取当前离线的登录用户对象
	 * 
	 * @return
	 * @throws Exception
	 */
	public static StaffUser getCurStaffUser() throws Exception {
		return checkUser;
	}

	/**
	 * 获取所有离线用户信息
	 * 
	 * @return
	 */
	public static List<StaffUserVO> getStaffUsrs() throws Exception {
		StaffUserSDAO searchDao = new StaffUserSDAO(ANRONGTEC_DB);
		return searchDao.queryStaffUserVOALL();// 正式警员只能通过PKI登录
	}

	/**
	 * 登录
	 * 
	 * @param staffUserVO
	 *            getStaffUsrs中获取的对象
	 * @param passwd
	 * @return JsonDataResult的code值为000表示成功,结果为泛型对象T;非000则失败,失败原因为msg
	 * @throws Exception
	 */
	public static JsonDataResult<String> login(StaffUserVO staffUserVO,
			String passwd) throws Exception {
		JsonDataResult<String> jr = new JsonDataResult<String>();
		StaffUserSDAO sdao = new StaffUserSDAO(ANRONGTEC_DB);
		StaffUser staffUser = sdao.queryBeanByName(staffUserVO.getStaffCode());
		String md5Pass = new MD5Impl().encode(new String(passwd));
		if (staffUser == null || !md5Pass.equals(staffUser.getLoginPassword())) {
			jr.setCode("020");
			jr.setMsg("密码错误或者用户名不存在！");
		} else {
			checkUser = staffUser;
			Staff s = new Staff();
			s.setStaffId(staffUser.getCreateStaffId());
			formalPolice = new StaffSDAO(ANRONGTEC_DB).queryBean(s);
			if (formalPolice == null) {
				jr.setCode("021");
				jr.setMsg("没有归属警员信息,请核实！");
			} else {
				EquiptMonitor monitorEntity = new EquiptMonitor();
				monitorEntity.setId(uuid32());
				monitorEntity.setEqtId(loginEqt.getEquiptId());
				monitorEntity
						.setActiveType(EquiptMonitorCont.ActiveTypeName.LOGIN);
				monitorEntity.setActiveTime(new Timestamp(System
						.currentTimeMillis()));
				monitorEntity
						.setActiveResult(EquiptMonitorCont.ACTION_RESULT_SUCC);
				monitorEntity.setActiveDetail("用户:" + checkUser.getStaffName()
						+ "(警员身份证号" + checkUser.getStaffCode() + ",归属警员:"
						+ formalPolice.getStaffCode() + ")登录移动终端系统.");
				addMonitorRecord(monitorEntity);
			}
		}

		return jr;
	}

	/**
	 * 当前用户注销
	 * 
	 * @param staffUserVO
	 * @throws Exception
	 */
	public static void logout(StaffUserVO staffUserVO) throws Exception {
		// 记录设备活动日志
		EquiptMonitor monitorEntity = new EquiptMonitor();
		monitorEntity.setId(uuid32());
		monitorEntity.setEqtId(loginEqt.getEquiptId());
		monitorEntity.setActiveType(EquiptMonitorCont.ActiveTypeName.LOGOUT);
		monitorEntity.setActiveTime(new Timestamp(System.currentTimeMillis()));
		monitorEntity.setActiveResult(EquiptMonitorCont.ACTION_RESULT_SUCC);
		monitorEntity.setActiveDetail("用户:" + checkUser.getStaffName()
				+ "(警员身份证号" + checkUser.getStaffCode() + ",归属警员:"
				+ formalPolice.getStaffCode() + ")退出移动终端系统.");
		addMonitorRecord(monitorEntity);
	}

	/**
	 * 核查人
	 * 
	 * @param eventId
	 *            事件ID，主要是处理人车物关联,32位的UUID
	 * @param recordId
	 *            记录ID，32位的UUID
	 * @param checkPersonInfo
	 * @return List<KeyPerson> 为null或集合为空 说明为正常人
	 * @throws Exception
	 */
	public synchronized static List<KeyPerson> checkPerson(String eventId,
			String recordId, CheckPersonInfo checkPersonInfo) throws Exception {
		List<KeyPerson> keyPersons = checkPerson(ANRONG_DATAS_PATHDIR
				+ "package", ANRONG_DATAS_PATHDIR + "package/package.db",
				checkPersonInfo.sfhm);
		KeyPerson keyPerson = null;
		if (keyPersons != null) {
			keyPerson = listToOneKeyPerson(keyPersons);
		}
		long time = System.currentTimeMillis();

		CrCheckevent crCheckevent = new CrCheckevent();
		crCheckevent.setId(eventId);
		CrCheckeventSDAO crCheckeventSDAO = new CrCheckeventSDAO(
				CHECKRECORDUPLOAD_DB);
		if (crCheckeventSDAO.queryBean(crCheckevent) == null) {
			crCheckevent.setCheckUser(checkUser.getStaffName());
			crCheckevent.setUserId(formalPolice.getStaffCode());
			crCheckevent.setEquiptId(loginEqt.getEquiptId());
			crCheckevent.setStartTime(new Timestamp(time));
			crCheckevent.setEndTime(new Timestamp(time));
			crCheckevent.setCheckpointId(loginEqt.getDeptId());
			crCheckevent.setAddres(checkPersonInfo.addres);
			crCheckevent.setPcddx(checkPersonInfo.gpsX);
			crCheckevent.setPcddy(checkPersonInfo.gpsY);
			crCheckevent.setRemark(checkPersonInfo.desc);

			crCheckeventSDAO.insert(crCheckevent);
		}

		CrPersionRecord perRecord = new CrPersionRecord();
		perRecord.setId(recordId);
		perRecord.setCheckeventId(eventId);
		perRecord.setSfhm(checkPersonInfo.sfhm);
		perRecord.setXm(checkPersonInfo.xm);
		perRecord.setMz(checkPersonInfo.mz);
		perRecord.setQfjg(checkPersonInfo.qfjq);
		perRecord.setYxqx(checkPersonInfo.yxqx);
		perRecord.setXb(checkPersonInfo.xb);

		perRecord.setCsrq(checkPersonInfo.csrq);
		perRecord.setSfzzz(checkPersonInfo.sfzzz);
		perRecord.setZp(checkPersonInfo.pic);// 身份证照片

		// ???是否可以取组织机构的前6位？
		perRecord.setProvince("");// 被核查人所在省
		perRecord.setCity("");// 被核查人所在市
		perRecord.setCounty("");// 被核查人所在区县

		perRecord.setPcsj(new Timestamp(time));
		perRecord.setCreateTime(new Timestamp(time));
		perRecord.setAllgenerateId(loginCurAsAllGenerate.getId());
		perRecord.setAllpackageVer(loginCurAsAllGenerate.getVer());

		perRecord.setSjly(company_ID);

		CrPersionRecordSDAO crPersionRecordSDAO = new CrPersionRecordSDAO(
				CHECKRECORDUPLOAD_DB);
		crPersionRecordSDAO.insert(perRecord);

		if (keyPerson != null) {
			CrBidPerson bidPer = new CrBidPerson();
			bidPer.setHcjlId(perRecord.getId());// 核查记录ID
			bidPer.setCheckeventId(eventId);// 核查事件ID
			bidPer.setTaskNames(keyPerson.getRwmc());// 比中的任务名称
			bidPer.setTaskId(keyPerson.getRwid());// 比中的任务ID
			bidPer.setPackageFirstIds(keyPerson.getPfirstid());// 审核布控包对应的第一次的包id
			bidPer.setPackageVerIds(keyPerson.getPverid());// 审核布控包对应的版本id
			bidPer.setPackageUser(keyPerson.getBklxr());//
			bidPer.setPackageMobile(keyPerson.getBklxfs());//
			bidPer.setRylb(keyPerson.getRylb());//
			bidPer.setSfzh(checkPersonInfo.sfhm);//
			bidPer.setPckssj(new Timestamp(time));//
			bidPer.setDescPerson("");//

			CrBidPersonSDAO crBidPersonSDAO = new CrBidPersonSDAO(
					CHECKRECORDUPLOAD_DB);
			crBidPersonSDAO.insert(bidPer);
		}

		return keyPersons;
	}

	/**
	 * 存疑人员
	 * 
	 * @param eventId
	 * @param recordId
	 * @param checkPersonInfo
	 * @param doubtfulDesc
	 * @throws Exception
	 */
	public static void doubtfulPerson(String eventId, String recordId,
			CheckPersonInfo checkPersonInfo, String doubtfulDesc)
			throws Exception {
		CrDoubtfulPerson doubtfulPerson = new CrDoubtfulPerson();
		doubtfulPerson.setId(uuid32());
		doubtfulPerson.setCheckeventId(eventId);
		doubtfulPerson.setHcjlId(recordId);
		doubtfulPerson.setSfzh(checkPersonInfo.sfhm);
		doubtfulPerson.setPckssj(new Timestamp(System.currentTimeMillis()));
		doubtfulPerson.setDescPerson(doubtfulDesc);

		CrDoubtfulPersonSDAO dao = new CrDoubtfulPersonSDAO(
				CHECKRECORDUPLOAD_DB);
		dao.insert(doubtfulPerson);
	}

	/**
	 * 处置人员
	 * 
	 * @param eventId
	 * @param recordId
	 * @param checkPersonInfo
	 * @param hcManagementInfo
	 * @throws Exception
	 */
	public static void hcManagementPerson(String eventId, String recordId,
			CheckPersonInfo checkPersonInfo, HcManagementInfo hcManagementInfo)
			throws Exception {
		CrHcManagement hcManagement = new CrHcManagement();
		hcManagement.setId(uuid32());
		hcManagement.setCheckeventId(eventId);
		hcManagement.setHcjlId(recordId);
		hcManagement.setType("1");
		hcManagement.setZjhm(checkPersonInfo.sfhm);
		hcManagement.setPckssj(new Timestamp(System.currentTimeMillis()));

		hcManagement.setXcspypzl(hcManagementInfo.xcspypzl);// 现场视频、音频资料

		hcManagement.setCzfs(hcManagementInfo.czfs);
		hcManagement.setDescCorr(hcManagementInfo.czDesc);

		CrHcManagementSDAO hcSDAO = new CrHcManagementSDAO(CHECKRECORDUPLOAD_DB);
		hcSDAO.insert(hcManagement);
	}

	/**
	 * 核查车辆
	 * 
	 * @param eventId
	 *            事件ID，主要是处理人车物关联,32位的UUID
	 * @param recordId
	 *            记录ID，32位的UUID
	 * @param CheckCarInfo
	 * @return List<KeyCar> 为null或集合为空 说明为正常
	 * @throws Exception
	 */
	public synchronized static List<KeyCar> checkCar(String eventId,
			String recordId, CheckCarInfo checkCarInfo) throws Exception {
		int checkType = 1;
		List<KeyCar> keyCars = checkCar(ANRONG_DATAS_PATHDIR + "package",
				ANRONG_DATAS_PATHDIR + "package/package.db", checkCarInfo.cphm,
				checkType, checkCarInfo.hpzl);
		KeyCar keyCar = null;
		if (keyCars != null) {
			keyCar = listToOneKeyCar(keyCars);
		}
		long time = System.currentTimeMillis();

		CrCheckevent crCheckevent = new CrCheckevent();
		crCheckevent.setId(eventId);
		CrCheckeventSDAO crCheckeventSDAO = new CrCheckeventSDAO(
				CHECKRECORDUPLOAD_DB);
		if (crCheckeventSDAO.queryBean(crCheckevent) == null) {
			crCheckevent.setCheckUser(checkUser.getStaffName());
			crCheckevent.setUserId(formalPolice.getStaffCode());
			crCheckevent.setEquiptId(loginEqt.getEquiptId());
			crCheckevent.setStartTime(new Timestamp(time));
			crCheckevent.setEndTime(new Timestamp(time));
			crCheckevent.setCheckpointId(loginEqt.getDeptId());
			crCheckevent.setAddres(checkCarInfo.addres);
			crCheckevent.setPcddx(checkCarInfo.gpsX);
			crCheckevent.setPcddy(checkCarInfo.gpsY);
			crCheckevent.setRemark(checkCarInfo.desc);

			crCheckeventSDAO.insert(crCheckevent);
		}

		CrCarRecord carRecord = new CrCarRecord();
		carRecord.setId(recordId);
		carRecord.setCheckeventId(eventId);
		// 是否可以从全国接口获取的信息获取？？？
		if (checkType == 1) {
			carRecord.setCp(checkCarInfo.cphm);
		} else if (checkType == 2) {
			carRecord.setClsbdm(checkCarInfo.clsbdm);
		} else if (checkType == 3) {
			carRecord.setFdjh(checkCarInfo.fdjh);
		}
		carRecord.setHpzl(checkCarInfo.hpzl);
		carRecord.setCzsfhm("");
		carRecord.setCzxm("");

		// ???是否可以取组织机构的前6位？
		carRecord.setProvince("");// 被核查人所在省
		carRecord.setCity("");// 被核查人所在市
		carRecord.setCounty("");// 被核查人所在区县

		carRecord.setPcsj(new Timestamp(time));
		carRecord.setCreateTime(new Timestamp(time));
		carRecord.setAllgenerateId(loginCurAsAllGenerate.getId());
		carRecord.setAllpackageVer(loginCurAsAllGenerate.getVer());

		carRecord.setSjly(company_ID);

		CrCarRecordSDAO crCarRecordSDAO = new CrCarRecordSDAO(
				CHECKRECORDUPLOAD_DB);
		crCarRecordSDAO.insert(carRecord);

		if (keyCar != null) {
			CrBidCar bidCar = new CrBidCar();
			bidCar.setHcjlId(carRecord.getId());// 核查记录ID
			bidCar.setCheckeventId(eventId);// 核查事件ID
			bidCar.setTaskNames(keyCar.getRwmc());// 比中的任务名称
			bidCar.setTaskId(keyCar.getRwid());// 比中的任务ID
			bidCar.setPackageFirstIds(keyCar.getPfirstid());// 审核布控包对应的第一次的包id
			bidCar.setPackageVerIds(keyCar.getPverid());// 审核布控包对应的版本id
			bidCar.setPackageUser(keyCar.getBklxr());//
			bidCar.setPackageMobile(keyCar.getBklxfs());//
			bidCar.setCllb(keyCar.getCllb());//
			bidCar.setCp(checkCarInfo.cphm);//
			bidCar.setPckssj(new Timestamp(time));//
			bidCar.setDescCar("");//

			CrBidCarSDAO crBidCarSDAO = new CrBidCarSDAO(CHECKRECORDUPLOAD_DB);
			crBidCarSDAO.insert(bidCar);
		}

		return keyCars;
	}

	/**
	 * 存疑车辆
	 * 
	 * @param eventId
	 * @param recordId
	 * @param checkCarInfo
	 * @param doubtfulDesc
	 * @throws Exception
	 */
	public static void doubtfulCar(String eventId, String recordId,
			CheckCarInfo checkCarInfo, String doubtfulDesc) throws Exception {
		CrDoubtfulCar doubtful = new CrDoubtfulCar();
		doubtful.setId(uuid32());
		doubtful.setCheckeventId(eventId);
		doubtful.setHcjlId(recordId);
		doubtful.setCph(checkCarInfo.cphm);
		doubtful.setPckssj(new Timestamp(System.currentTimeMillis()));
		doubtful.setDescCar(doubtfulDesc);

		CrDoubtfulCarSDAO dao = new CrDoubtfulCarSDAO(CHECKRECORDUPLOAD_DB);
		dao.insert(doubtful);
	}

	/**
	 * 处置车辆
	 * 
	 * @param eventId
	 * @param recordId
	 * @param checkCarInfo
	 * @param hcManagementInfo
	 * @throws Exception
	 */
	public static void hcManagementCar(String eventId, String recordId,
			CheckCarInfo checkCarInfo, HcManagementInfo hcManagementInfo)
			throws Exception {
		CrHcManagement hcManagement = new CrHcManagement();
		hcManagement.setId(uuid32());
		hcManagement.setCheckeventId(eventId);
		hcManagement.setHcjlId(recordId);
		hcManagement.setType("2");
		hcManagement.setZjhm(checkCarInfo.cphm);
		hcManagement.setPckssj(new Timestamp(System.currentTimeMillis()));

		hcManagement.setXcspypzl(hcManagementInfo.xcspypzl);// 现场视频、音频资料

		hcManagement.setCzfs(hcManagementInfo.czfs);
		hcManagement.setDescCorr(hcManagementInfo.czDesc);

		CrHcManagementSDAO hcSDAO = new CrHcManagementSDAO(CHECKRECORDUPLOAD_DB);
		hcSDAO.insert(hcManagement);
	}

	private static List<KeyPerson> checkPerson(String packageDir,
			String packageDBfilePath, String sfz) {
		// long now = System.currentTimeMillis();
		String sheng = sfz.substring(0, 2);
		String shi = sfz.substring(2, 4);
		String xian = sfz.substring(4, 6);
		String xianFilePath = packageDir + "/" + sheng + "/" + shi + "/" + xian
				+ ".dat";
		File f = new File(xianFilePath);
		if (!f.exists()) {
			return null;
		}
		List<KeyPerson> list = new ArrayList<KeyPerson>();
		FileChannel fc = null;
		FileLock fl = null;
		try {
			fc = new FileInputStream(f).getChannel();
			fl = fc.tryLock(0, Long.MAX_VALUE, true);
			if (fl == null) {
				fc.close();
				return null;
			}

			byte[] entry = new byte[2048];
			ByteBuffer bb = ByteBuffer.wrap(entry);
			int loaded = 0;
			while (true) {
				bb.clear();
				bb.limit(4);
				bufferRead(fc, bb);
				if (bb.remaining() > 0) {
					break;
				}
				bb.flip();
				int tt = bb.getInt();// 没用的数据

				int columnsSize = readInt(fc, bb);// 列数
				byte[] da0x20 = null;
				String[] s = new String[columnsSize];
				KeyPerson person = null;
				for (int j = 0; j < columnsSize; j++) {
					int daLen = readInt(fc, bb);
					if (daLen == -1 && j == 0) {
						break;
					}

					da0x20 = readByte(fc, bb, daLen);
					s[j] = new String(da0x20, UTF_8);

					if (j == columnsSize - 1) {
						loaded++;

						String sfzh = s[0] + s[6] + s[11];
						if (sfzh.equals(sfz)) {
							person = new KeyPerson();
							person.setSfzh(s[0] + s[6] + s[11]);
							person.setRylb(s[4]);
							person.setClfs(s[5]);
							person.setAqms(s[3]);
							person.setBklxr(s[10]);
							person.setBklxfs(s[9]);
							person.setRwmc(getRwmc(s[8]));
							person.setRwid(s[7]);
							person.setPfirstid(s[1]);
							person.setPverid(s[2]);
							if (checkTaskScope(packageDBfilePath, s[7])) {// 如果在布控范围内则加上
								list.add(person);
							}
						}
						j = -1;
						s = new String[columnsSize];

					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fl != null) {
				try {
					fl.release();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			if (fc != null) {
				try {
					fc.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return list;
	}

	/**
	 * 
	 * @param cphm可以是车辆识别代码
	 *            ,也可以是发动机号 int checkType = 0;//1核查车牌2核查车辆识别代码3核查发动机号
	 * @return
	 */
	public static List<KeyCar> checkCar(String packageDir,
			String packageDBfilePath, String cph, int checkType, String hpzl) {
		String sheng = cph.substring(0, 1);
		String shi = cph.substring(1, 2);
		String shiFilePath = packageDir + "/" + sheng + "/" + shi + ".dat";
		File f = new File(shiFilePath);
		if (!f.exists()) {
			return null;
		}
		List<KeyCar> list = new ArrayList<KeyCar>();
		FileChannel fc = null;
		FileLock fl = null;
		try {
			fc = new FileInputStream(f).getChannel();
			fl = fc.tryLock(0, Long.MAX_VALUE, true);
			if (fl == null) {
				fc.close();
				return null;
			}

			byte[] entry = new byte[2048];
			ByteBuffer bb = ByteBuffer.wrap(entry);
			int loaded = 0;
			while (true) {
				bb.clear();
				bb.limit(4);
				bufferRead(fc, bb);
				if (bb.remaining() > 0) {
					break;
				}
				bb.flip();
				int tt = bb.getInt();// 没用的数据

				int columnsSize = readInt(fc, bb);// 列数
				byte[] da0x20 = null;
				String[] s = new String[columnsSize];
				KeyCar car = null;
				for (int j = 0; j < columnsSize; j++) {
					int daLen = readInt(fc, bb);
					if (daLen == -1 && j == 0) {
						break;
					}

					da0x20 = readByte(fc, bb, daLen);
					s[j] = new String(da0x20, UTF_8);

					if (j == columnsSize - 1) {
						loaded++;

						boolean zb = false;
						if (checkType == 1) {
							if (s[5].equals(cph)) {
								if (columnsSize >= 16 && s[15].length() > 0) {// 为了兼容之前的数据
									if (hpzl.equals(s[15])) {
										zb = true;
									}
								} else {
									zb = true;
								}
							}
						} else if (checkType == 2) {
							if (s[8].equals(cph)) {
								zb = true;
							}
						} else if (checkType == 3) {
							if (s[10].equals(cph)) {
								zb = true;
							}
						}

						if (zb) {
							car = new KeyCar();
							car.setCphm(s[5]);
							car.setCzsfzh(s[6]);
							car.setCzxm(s[7]);
							car.setClsbdm(s[8]);
							car.setClys(s[9]);
							car.setFdjh(s[10]);
							car.setCllb(s[3]);
							car.setClfs(s[4]);
							car.setAqms(s[2]);
							car.setBklxr(s[14]);
							car.setBklxfs(s[13]);
							car.setRwmc(getRwmc(s[12]));
							car.setRwid(s[11]);
							car.setPfirstid(s[0]);
							car.setPverid(s[1]);
							if (columnsSize >= 16) {// 为了兼容之前的数据
								car.setHpzl(s[15]);
							}

							if (checkTaskScope(packageDBfilePath, s[11])) {// 如果在布控范围内则加上
								list.add(car);
							}
						}

						j = -1;
						s = new String[columnsSize];
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fl != null) {
				try {
					fl.release();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if (fc != null) {
				try {
					fc.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		return list;
	}

	private static boolean checkTaskScope(String packageDBfilePath,
			String taskIds) {
		File f = new File(packageDBfilePath);
		if (!f.exists() || taskIds == null || curDept.getDeptId() == null) {
			return true;
		}

		String[] idArrays = taskIds.split(",");
		if (idArrays.length < 1) {
			return true;
		}

		String ids = "";
		for (int i = 0; i < idArrays.length; i++) {
			if (i != 0) {
				ids += ",";
			}
			ids += "'" + idArrays[i] + "'";
		}
		TaskScopeSDAO dao = new TaskScopeSDAO(packageDBfilePath);
		try {
			List<TaskScope> scpoes = dao.queryListByTaskIds(ids);
			if (scpoes.size() < 1) {
				return true;// 没有定义范围
			}

			for (TaskScope scpoe : scpoes) {
				if (scpoe.getType().equals("1")) {// 组织机构
					if (scpoe.getDeptId().length() != 12) {// 如果是检查站id,取所在父的组织机构id
						if (isSameDeptTree(scpoe.getDeptId(),
								curDept.getUpDeptId())) {
							return true;
						}
					} else {
						if (isSameDeptTree(scpoe.getDeptId(),
								curDept.getDeptId())) {
							return true;
						}
					}
				} else {// 如果是检查站就是检查站id相等
					if (scpoe.getDeptId().equals(curDept.getDeptId())) {
						return true;
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			return true;// 捕获异常，数据就要抛出，人为去确定
		}

		return false;
	}

	/**
	 * 必须保证组织机构 都是12位的，且每2位代表所在树的节点位置 判断当前组织机构curDeptId 是不是 挂在
	 * scopeDeptId组织机构树下的 id
	 * 
	 * @param scopeDeptId
	 * @param curDeptId
	 * @return
	 */
	private static boolean isSameDeptTree(String scopeDeptId, String curDeptId) {
		if (scopeDeptId.length() != 12 || curDeptId.length() != 12) {
			return false;
		}
		if (scopeDeptId.equals(curDeptId)) {
			return true;
		} else if (scopeDeptId.substring(0, 10).equals(
				curDeptId.substring(0, 10))) {
			return scopeDeptId.substring(10).equals("00") ? true : false;
		} else if (scopeDeptId.substring(0, 8)
				.equals(curDeptId.substring(0, 8))) {
			return scopeDeptId.substring(8).equals("0000") ? true : false;
		} else if (scopeDeptId.substring(0, 6)
				.equals(curDeptId.substring(0, 6))) {
			return scopeDeptId.substring(6).equals("000000") ? true : false;
		} else if (scopeDeptId.substring(0, 4)
				.equals(curDeptId.substring(0, 4))) {
			return scopeDeptId.substring(4).equals("00000000") ? true : false;
		} else if (scopeDeptId.substring(0, 2)
				.equals(curDeptId.substring(0, 2))) {
			return scopeDeptId.substring(2).equals("0000000000") ? true : false;
		} else {
			return false;
		}
	}

	public static KeyCar listToOneKeyCar(List<KeyCar> keys) {
		if (keys.size() == 0) {
			return null;
		} else if (keys.size() == 1) {
			return keys.get(0);
		} else {
			KeyCar car = keys.get(0);
			for (int i = 1; i < keys.size(); i++) {

				KeyCar k = keys.get(i);

				car.setCllb(AandB(car.getCllb(), k.getCllb()));
				car.setClfs(AandB(car.getClfs(), k.getClfs()));
				car.setAqms(AandB(car.getAqms(), k.getAqms()));
				car.setBklxr(AandB(car.getBklxr(), k.getBklxr()));
				car.setBklxfs(AandB(car.getBklxfs(), k.getBklxfs()));

				car.setRwmc(AandB(car.getRwmc(), k.getRwmc()));
				car.setRwid(AandB(car.getRwid(), k.getRwid()));
				car.setPfirstid(AandB(car.getPfirstid(), k.getPfirstid()));
				car.setPverid(AandB(car.getPverid(), k.getPverid()));
			}
			return car;
		}
	}

	public static KeyPerson listToOneKeyPerson(List<KeyPerson> keys) {
		if (keys.size() == 0) {
			return null;
		} else if (keys.size() == 1) {
			return keys.get(0);
		} else {
			KeyPerson car = keys.get(0);
			for (int i = 1; i < keys.size(); i++) {
				KeyPerson k = keys.get(i);
				car.setRylb(AandB(car.getRylb(), k.getRylb()));
				car.setClfs(AandB(car.getClfs(), k.getClfs()));
				car.setAqms(AandB(car.getAqms(), k.getAqms()));
				car.setBklxr(AandB(car.getBklxr(), k.getBklxr()));
				car.setBklxfs(AandB(car.getBklxfs(), k.getBklxfs()));

				car.setRwmc(AandB(car.getRwmc(), k.getRwmc()));
				car.setRwid(AandB(car.getRwid(), k.getRwid()));
				car.setPfirstid(AandB(car.getPfirstid(), k.getPfirstid()));
				car.setPverid(AandB(car.getPverid(), k.getPverid()));
			}
			return car;
		}
	}

	/**
	 * 因三大数据源,写死,所以再获取下任务名称
	 * 
	 * @param rwmc
	 * @return
	 */
	public static String getRwmc(String rwmc) {
		if (rwmc == null) {
			return "";
		}
		if (rwmc.equals("DM") || rwmc.equals("EBJA")) {
			return "常态布控任务";
		} else {
			return rwmc;
		}
	}

	private static String AandB(String a, String b) {
		if (isNotBlank(b)) {
			if (isNotBlank(a)) {
				return a + ";" + b;
			} else {
				return b;
			}
		}
		return "";
	}

	private static boolean isNotBlank(String a) {
		if (a == null || a.trim().length() < 1) {
			return false;
		}
		return true;
	}

	public static void bufferRead(FileChannel fc, ByteBuffer bb)
			throws IOException {
		while (bb.remaining() > 0) {
			if (fc.read(bb) < 0) {
				break;
			}
		}
	}

	public static int readInt(FileChannel fc, ByteBuffer bb) throws IOException {
		bb.clear();
		bb.limit(4);
		bufferRead(fc, bb);
		bb.flip();
		return bb.getInt();
	}

	public static byte[] readByte(FileChannel fc, ByteBuffer bb, int length)
			throws IOException {
		bb.clear();
		byte[] da0x20 = new byte[length];
		bb.limit(length);
		bufferRead(fc, bb);
		bb.flip();
		bb.get(da0x20);
		return da0x20;
	}

	public static void outFileStartData(ByteBuffer bb, FileChannel fc)
			throws IOException {
		bb.clear();
		bb.putInt(130);
		bb.putInt(12);
		bb.flip();
		fc.write(bb);
	}

	public static void outRowData(String[] ds, ByteBuffer bb, FileChannel fc)
			throws IOException {
		for (String data : ds) {
			bb.clear();
			bb.putInt(data.getBytes("UTF-8").length);
			bb.put(data.getBytes("UTF-8"));
			bb.flip();
			fc.write(bb);
		}
	}

	public static void outFileOverData(ByteBuffer bb, FileChannel fc)
			throws IOException {
		bb.clear();
		bb.putInt(-1);
		bb.flip();
		fc.write(bb);
	}

	public static void main(String[] args) throws Exception {
		// SDKService.init("E:\\temp", "11111111", "anrongtec");

		List<StaffUserVO> users = SDKService.getStaffUsrs();
		for (StaffUserVO u : users) {
			System.out.println(u.toString());
		}

		JsonDataResult<String> re = SDKService.login(users.get(0), "111111");
		System.out.println(re.isSuccess());
	}
}
